package cn.shujuhai.common.config;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotRoleException;
import cn.dev33.satoken.util.SaResult;
import cn.shujuhai.common.aop.SysLogAspect;
import cn.shujuhai.common.pluging.exception.UnknownPathException;
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.Model;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.resource.NoResourceFoundException;
import org.thymeleaf.exceptions.TemplateProcessingException;


@RestControllerAdvice
public class GlobalExceptionHandler {

    @Value("${server.servlet.context-path}")
    private String baseUrl;

    private static final Logger logger = LoggerFactory.getLogger(SysLogAspect.class);

    /**
     * 系统异常
     *
     * @param ex 异常信息
     * @return 自定义错误页面或消息
     */
    @ExceptionHandler(Exception.class)
    public ResponseEntity<SaResult> handleException(Exception ex) {
        logger.error("系统异常: {}", ex.getMessage(), ex);
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(SaResult.error("服务器内部错误: " + ex.getMessage()));
    }

    /**
     * 运行时异常
     *
     * @param ex 异常信息
     * @return 自定义错误页面或消息
     */
    @ExceptionHandler(RuntimeException.class)
    public ResponseEntity<SaResult> handleRuntimeException(RuntimeException ex) {
        logger.error("运行时异常: {}", ex.getMessage(), ex);
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(SaResult.error(ex.getMessage()));
    }


    /**
     * 未登录访问异常
     *
     * @param ex 异常信息
     * @return 自定义错误页面或消息
     */
    @ExceptionHandler(NotLoginException.class)
    public Object handleNotLoginException(NotLoginException ex) {
        logger.warn("未登录访问: {}", ex.getMessage());
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String acceptHeader = request.getHeader("Content-Type");

        if (acceptHeader != null && acceptHeader.contains("application/json")) {
            // 返回 JSON 格式的错误信息
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(SaResult.error("未登录，请先登录"));
        } else {
            // 返回登录页面
            ModelAndView modelAndView = new ModelAndView("page/login");
            modelAndView.addObject("script", "<script>window.open('" + baseUrl + "page/login', '_top');</script>");
            return modelAndView;
        }
    }

    /**
     * 无角色异常
     *
     * @param ex    异常信息
     * @param model model
     * @return 自定义错误页面或消息
     */
    @ExceptionHandler(NotRoleException.class)
    public ModelAndView handleNotRoleException(NotRoleException ex, Model model) {
        logger.error("无角色异常: {}", ex.getMessage(), ex);
        model.addAttribute("message", "用户没有所需角色");
        return new ModelAndView("page/common/error/403", model.asMap());
    }

    /**
     * 栏目页面未找到异常
     *
     * @param ex 异常信息
     * @return 自定义错误页面或消息
     */
    @ExceptionHandler(ResponseStatusException.class)
    public ModelAndView handleResponseStatusException(ResponseStatusException ex) {
        logger.error("栏目页面未找到: {}", ex.getMessage(), ex);
        return new ModelAndView("page/common/error/column404");
    }

    /**
     * 未知路径异常
     *
     * @param ex 异常信息
     * @return 自定义错误页面或消息
     */
    @ExceptionHandler(UnknownPathException.class)
    public ModelAndView handleUnknownPathException(UnknownPathException ex) {
        logger.error("未知路径异常: {}", ex.getMessage());
        ModelAndView modelAndView = new ModelAndView("page/common/error/404");
        modelAndView.addObject("msg", ex.getMessage());

        return modelAndView;
    }

    /**
     * 模板解析异常
     *
     * @param ex 异常信息
     * @return 自定义错误页面或消息
     */
    @ExceptionHandler(TemplateProcessingException.class)
    public ModelAndView handleTemplateProcessingException(TemplateProcessingException ex) {
        logger.error("模板解析异常: {}", ex.getMessage(), ex);
        return new ModelAndView("page/common/error/column404");
    }

    /**
     * 参数校验异常
     *
     * @param ex 异常信息
     * @return 自定义错误页面或消息
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public String handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
        logger.error("参数校验异常: {}", ex.getMessage(), ex);
        StringBuilder errorMsg = new StringBuilder();
        for (FieldError error : ex.getBindingResult().getFieldErrors()) {
            errorMsg.append(error.getDefaultMessage())
                    .append("; ");
        }
        return errorMsg.toString();
    }


    /**
     * 静态资源异常
     *
     * @param ex 异常信息
     * @return 自定义错误页面或消息
     */
    @ExceptionHandler(NoResourceFoundException.class)
    public ModelAndView handle(NoResourceFoundException ex) {
        logger.error("静态资源异常: {}", ex.getMessage(), ex);
        return new ModelAndView("page/common/error/column404");
    }
}